﻿using System;
using System.Globalization;
using AdvancedGod.People;

namespace AdvancedGod.UserInterface
{
  /// <summary>
  /// Manages console output
  /// </summary>
  public class ConsolePrinter
  {
    #region private vars
    /// <summary>
    /// Colore scheme for console's instance
    /// </summary>
    private ColorScheme colorScheme;
    #endregion

    #region public methods
    /// <summary>
    /// Constructor. Creates console printer with default color scheme
    /// </summary>
    public ConsolePrinter()
    {
      colorScheme = new ColorScheme();
    }

    /// <summary>
    /// Prints welcome message
    /// </summary>
    public void PrintWelcome()
    {
      Console.WriteLine(ConsoleMessages.Welcome);
    }

    /// <summary>
    /// Prints exit message
    /// </summary>
    public void PrintExit()
    {
      Console.WriteLine();
      Console.WriteLine(ConsoleMessages.End);
    }

    /// <summary>
    /// Prints program description
    /// </summary>
    public void PrintProgramDescription()
    {
      Console.WriteLine(ConsoleMessages.Description);
    }

    /// <summary>
    /// Prints message about no work on sunday
    /// </summary>
    public void PrintCanNotWorkAtSunday()
    {
      Console.WriteLine(ConsoleMessages.NoWorkOnSunday);
    }

    /// <summary>
    /// Prints info about result child
    /// </summary>
    /// <param name="child">result child which info will be printed</param>
    public void PrintResultChild(IHasName child)
    {
      if (child == null)
      {
        PrintBadResult(ConsoleMessages.NotLikes);
      }
      if (child is Book)
      {
        PrintBookInfo(child as Book);
      }
      else
      {
        PrintHuman(child as Human);
      }
      Console.WriteLine();

    }

    /// <summary>
    /// Prints description of coupling pair
    /// </summary>
    /// <param name="secondHuman">first human</param>
    /// <param name="firstHuman">second human</param>
    public void PrintCouplingHumansDescription(Human secondHuman, Human firstHuman)
    {
      Console.WriteLine();
      Console.WriteLine(ConsoleMessages.CouplingStart);
      PrintHuman(firstHuman);
      PrintHuman(secondHuman);
      Console.WriteLine();
      Console.WriteLine();
    }

    /// <summary>
    /// Prints error about copupling of peoples with same sex
    /// </summary>
    /// <param name="sex">sex of peoples trying to couple</param>
    public void PrintSameSex(Sex sex)
    {
      string sexDescr = sex == Sex.Male ? Humans.SexMale : Humans.SexFemale;
      string line = string.Format(CultureInfo.CurrentCulture,
        ConsoleMessages.SameSex, sexDescr);
      PrintBadResult(line);
      Console.WriteLine();
    }

    /// <summary>
    /// Prints no attribute error
    /// </summary>
    /// <param name="type1">first type (for which where is no 
    /// pertient attribute with pair value of type type2)</param>
    /// <param name="type2">second type</param>
    public void PrintNoAttribute(Type type1, Type type2)
    {
      Console.BackgroundColor = colorScheme.ErrorBackground;
      Console.ForegroundColor = colorScheme.ErrorForeground;
      string line = string.Format(CultureInfo.CurrentCulture,
        ConsoleMessages.NoAttribute,
        type1.Name, type2.Name);
      Console.WriteLine(line);
      Console.ResetColor();
      Console.WriteLine();
    }

    /// <summary>
    /// Methods for type printing (unused)
    /// </summary>
    /// <param name="iHasName">instance which type will be printed</param>
    public void PrintType(IHasName iHasName)
    {
      Console.WriteLine(Humans.IHasNameType, iHasName.GetType());
    }

    /// <summary>
    /// Methods for name printing (unused)
    /// </summary>
    /// <param name="iHasName">instance which name will be printed</param>
    public void PrintName(IHasName iHasName)
    {
      Console.WriteLine(Humans.IHasNameName, iHasName.Name);
    }

    #endregion

    #region private methods

    /// <summary>
    /// Prints info about human
    /// </summary>
    /// <param name="human">human which info will be printed</param>
    private void PrintHuman(Human human)
    {
      if (human is Botan)
      {
        PrintHumanInfo(human as Botan);
        return;
      }
      if (human is Student)
      {
        PrintHumanInfo(human as Student);
        return;
      }
      if (human is SmartGirl)
      {
        PrintHumanInfo(human as SmartGirl);
        return;
      }
      if (human is PrettyGirl)
      {
        PrintHumanInfo(human as PrettyGirl);
        return;
      }
      if (human is Girl)
      {
        PrintHumanInfo(human as Girl);
        return;
      }

      Console.WriteLine();
    }

    /// <summary>
    /// Prints student's info
    /// </summary>
    /// <param name="student">student, which info will be printed</param>
    private void PrintHumanInfo(Student student)
    {
      Console.BackgroundColor = colorScheme.StudentBackground;
      Console.ForegroundColor = colorScheme.StudentForeground;

      string girlDescription = string.Format(CultureInfo.CurrentCulture, Humans.Student,
        student.Age, student.Name, student.Surname);

      Console.WriteLine(girlDescription);

      Console.ResetColor();
    }

    /// <summary>
    /// Prints botan's info
    /// </summary>
    /// <param name="botan">botan, which info will be printed</param>
    private void PrintHumanInfo(Botan botan)
    {
      Console.BackgroundColor = colorScheme.BotanBackground;
      Console.ForegroundColor = colorScheme.BotanForeground;

      string botanDescription = string.Format(CultureInfo.CurrentCulture,
        Humans.Botan, botan.Age, botan.Name, botan.Surname, botan.AveargeMark);

      Console.WriteLine(botanDescription);

      Console.ResetColor();
    }

    /// <summary>
    /// Prints girl's info
    /// </summary>
    /// <param name="girl">student, which info will be printed</param>
    private void PrintHumanInfo(Girl girl)
    {
      PrintHumanInfo(girl, colorScheme.GirlBackground,
        colorScheme.GirlForeground);
    }

    /// <summary>
    /// Prints smart girl's info
    /// </summary>
    /// <param name="smartGirl">student, which info will be printed</param>
    private void PrintHumanInfo(SmartGirl smartGirl)
    {
      PrintHumanInfo(smartGirl, colorScheme.SmartGirlBackground,
        colorScheme.SmartGirlForeground);
    }

    /// <summary>
    /// Prints pretty girl's info
    /// </summary>
    /// <param name="prettyGirl">student, which info will be printed</param>
    private void PrintHumanInfo(PrettyGirl prettyGirl)
    {
      PrintHumanInfo(prettyGirl, colorScheme.PrettyGirlBackground,
        colorScheme.PrettyGirlForeground);
    }

    /// <summary>
    /// Prints any girl's info with specified background and foreground colors
    /// </summary>
    /// <param name="girl"></param>
    /// <param name="background"></param>
    /// <param name="foreground"></param>
    private void PrintHumanInfo(Girl girl, ConsoleColor background,
      ConsoleColor foreground)
    {
      Console.BackgroundColor = background;
      Console.ForegroundColor = foreground;

      Type girlType = girl.GetType();
      string girlDescription = string.Format(CultureInfo.CurrentCulture,
        Humans.AnyGirl, girlType.Name, girl.Age, girl.Name, girl.Surname);

      Console.WriteLine(girlDescription);

      Console.ResetColor();
    }

    /// <summary>
    /// Prints info about book
    /// </summary>
    /// <param name="book">book, whch info will be printed</param>
    private void PrintBookInfo(Book book)
    {
      Console.BackgroundColor = colorScheme.BookBackground;
      Console.ForegroundColor = colorScheme.BookForeground;

      string bookDescription = string.Format(CultureInfo.CurrentCulture,
        Humans.Book, book.Name);

      Console.WriteLine(bookDescription);

      Console.ResetColor();
    }

    /// <summary>
    /// Prints message about bad result of coupling
    /// </summary>
    /// <param name="message">meddage to be printed</param>
    private void PrintBadResult(string message)
    {
      Console.BackgroundColor = colorScheme.BadResultBackground;
      Console.ForegroundColor = colorScheme.BadResultForeground;

      Console.WriteLine(message);

      Console.ResetColor();
    }

    #endregion
  }
}
